
#include "RtBase.h"
#include "RtHttpUtilClasses.h"
#include "RtHttpUrl.h"

LPCSTR CRtHttpUrl::s_pszSchemeHttp = "http";
LPCSTR CRtHttpUrl::s_pszSchemeHttps = "https";
LPCSTR CRtHttpUrl::s_pszSchemeFile = "file";

CRtHttpUrl::CRtHttpUrl()
	: m_wPort(0)
{
}

CRtHttpUrl::~CRtHttpUrl()
{
}

BOOL CRtHttpUrl::Init(const CRtString &aSepc)
{
	LPCSTR pSrc = aSepc.c_str();
	while (pSrc && *pSrc == ' ') 
		++pSrc;
	if (!pSrc || !*pSrc)
		return FALSE;

	if (!strncasecmp(pSrc, "http://", 7)) {
		m_strScheme = s_pszSchemeHttp;
		pSrc += 7;
	} else if (!strncasecmp(pSrc, "https://", 8)) {
		m_strScheme = s_pszSchemeHttps;
		pSrc += 8;
	} else if (!strncasecmp(pSrc, "file://", 7)) {
		m_strScheme = s_pszSchemeFile;
		pSrc += 7;
	} else
		return FALSE;

	LPCSTR pPath = strchr(pSrc, '/');
	if (m_strScheme == s_pszSchemeFile) {
		if (pPath) {
#ifdef RT_WIN32
			// check whether it likes "C:/..."
			if (*(pPath-1) == ':' && isalpha(*(pPath-2)))
				pPath -= 2;
			else if (isalpha(*(pPath+1)))
				++pPath;
#endif // RT_WIN32
		} else
			pPath = pSrc;

		m_strPath = pPath;
#ifdef RT_WIN32
		for (CRtString::size_type i = 0; i < m_strPath.length(); i++) {
			if (m_strPath[i] == '/') 
				m_strPath[i] = '\\';
		}
#endif // RT_WIN32
	} else {
		if (!pPath) {
			if (!SetNameAndPort(CRtString(pSrc)))
				return FALSE;
		} else {
			CRtString strNamePort(pSrc, pPath - pSrc);
			if (!SetNameAndPort(strNamePort))
				return FALSE;
		}
		SetPath(pPath);
	}
	return TRUE;
}

WORD CRtHttpUrl::GetPort()
{
	return m_wPort;
}

CRtString CRtHttpUrl::GetHostName()
{
	return m_strHostName;
}

void CRtHttpUrl::SetPort(WORD aPort)
{
	m_wPort = aPort;
	if (m_wPort == 0)
		m_wPort = GetDefaultPort();
	m_strSpec.resize(0);
}

void CRtHttpUrl::SetPath(const CRtString &aObjName)
{
	if (!aObjName.empty()) 
		m_strPath = aObjName;
	else
		m_strPath = '/';
	m_strSpec.resize(0);
}

CRtString CRtHttpUrl::GetPath()
{
	return m_strPath;
}

CRtString CRtHttpUrl::GetScheme()
{
	return m_strScheme;
}

CRtString CRtHttpUrl::GetAsciiSpec()
{
	if (m_strSpec.empty()) {
		m_strSpec.reserve(64);
		m_strSpec = m_strScheme;
		m_strSpec += "://";
		m_strSpec += GetNameAndPort();
		
		if (!m_strPath.empty()) {
			if (m_strPath[0] != '/')
				m_strSpec += '/';
			m_strSpec += m_strPath;
		} else
			m_strSpec += '/';
	}
	return m_strSpec;
}

CRtString CRtHttpUrl::GetNameAndPort(BOOL bAddPort)
{
	CRtString strRetName = m_strHostName;
	if (bAddPort || m_wPort != GetDefaultPort()) {
		strRetName += ':';
		char szPort[16];
		sprintf(szPort, "%hu", m_wPort);
		strRetName += szPort;
	}
	return strRetName;
}

BOOL CRtHttpUrl::SetNameAndPort(const CRtString &aSrvName)
{
	CRtString strObj(aSrvName);
	if (strObj.empty())
		return FALSE;

	CRtString::size_type nFind = strObj.find(':', 0);
	if (nFind == CRtString::npos) {
		m_strHostName = strObj;
		SetPort(0);
	} else {
		m_strHostName = strObj.substr(0, nFind);
		CRtString strPort = strObj.substr(nFind+1);
		SetPort(atoi(strPort.c_str()));
	}

	if (m_strHostName.empty())
		return FALSE;
	m_strSpec.resize(0);
	return TRUE;
}

WORD CRtHttpUrl::GetDefaultPort()
{
	WORD nPort = 0;
	if (m_strScheme == s_pszSchemeHttp)
		nPort = 80;
	else if (m_strScheme == s_pszSchemeHttps)
		nPort = 443;
	return nPort;
}
